//read.cpp
//author: aandriyash

#include "utils.h"

#include <stdio.h>
#include <cstdlib>
#include <cstring>

#include <iostream>

int ReadFromRAID01(
    FILE* pFile 
    , int blockNumber 
    , int totalDisks 
    , int totalBlocks
    , int blockSize
) 
{
    RETURN_IF_ERROR(Mapping(totalDisks, totalBlocks, blockSize, false)); 

    int offset = (blockNumber - 1) * blockSize;
    for (int i = 1; i < totalDisks; i += 2)
    {
        fputs(ppMappedDataArray[i] + offset, pFile); //read mappedData
    }
  
    RETURN_IF_ERROR(Unmapping(totalDisks, totalBlocks, blockSize, false)); 
    
    return 0;
}

int ReadFromRAID10(
    FILE* pFile
    , int blockNumber 
    , int totalDisks 
    , int totalBlocks
    , int blockSize
) 
{
    RETURN_IF_ERROR(Mapping(totalDisks, totalBlocks, blockSize, false)); 
    
    int offset = blockSize * (blockNumber - 1);
    fputs(ppMappedDataArray[1] + offset, pFile);//read mappedData
  
    RETURN_IF_ERROR(Unmapping(totalDisks, totalBlocks, blockSize, false));
    
    return 0;
}

int main(
    int argc
    , char* argv[]
)
{
    if (argc < 3) 
    {
        std::cout << "Not enough parameters\n";
        return 1;
    }

    RaidConfig raidConf;
    raidConf.Read();     

    RETURN_IF_ERROR_TRACE((IsDiskCrashed(raidConf.totalDisks, false)), ("Rebuild RAID.\n"));

    int blockNumber = atoi(argv[1]);
    if ((blockNumber == 0) || (blockNumber > raidConf.totalBlocks)) 
    {
        std::cout << "Number of blocks must be 1.." << raidConf.totalBlocks << "\n";
        return 1;
    }

    FILE * pFile = fopen(argv[2], "wb+");
    if(NULL == pFile) 
    {
        std::cout << "Can't create or open file " << pFile << "\n";
        return 1;
    }
    
    int err = 0;
    switch (raidConf.raidLevel) 
    {
        case 1:
            err = ReadFromRAID01(
                        pFile
                        , blockNumber
                        , raidConf.totalDisks
                        , raidConf.totalBlocks
                        , raidConf.blockSize
                   );
            break;
        case 10:
            err = ReadFromRAID10(
                        pFile
                        , blockNumber
                        , raidConf.totalDisks
                        , raidConf.totalBlocks
                        , raidConf.blockSize
                   );
            break;
        default:
            err = 1;
            break;
    }
    
    fclose(pFile);
    
    return err;
}

